package com.ouc.common.utils;

import org.springframework.lang.Nullable;

import java.util.regex.Pattern;

public class ColorUtil {

  private ColorUtil() {
  }

  private static final String COLOR_REGEX = "^#[0-9abcdefABCDEF]{6}$";  //颜色字符串表达式
  private static Pattern colorPattern = Pattern.compile(COLOR_REGEX);  //颜色字符串模板

  /**
   * 颜色内插值
   * 向两个颜色之间插入中间值
   *
   * @param startColor 起始颜色。格式："#000000";
   * @param endColor   结束颜色。格式："#ffffff";
   * @return 插值颜色，格式："#05fb07"
   */
  public static String interpolate(String startColor, String endColor) {
    return interpolate(startColor, endColor, null);
  }

  /**
   * 颜色内插值
   * 向两个颜色之间插值，根据percent，返回相应的颜色值
   *
   * @param startColor 起始颜色。格式："#000000";
   * @param endColor   结束颜色。格式："#ffffff";
   * @param percent    百分比，即插值方法在两个颜色之间的比例，取值[0-1]。如果不传参，默认0.5，取中间值
   * @return 插值颜色，格式："#05fb07"
   */
  public static String interpolate(String startColor, String endColor, @Nullable Double percent) {
    percent = percent == null ? 0.5 : percent;
    int[] rgbStart = getRgb(startColor);
    int[] rgbEnd = getRgb(endColor);
    if (rgbStart == null || rgbEnd == null) {
      return null;
    }
    if (percent == 0) {
      return startColor;
    }
    if (percent == 1) {
      return endColor;
    }

    StringBuilder sb = new StringBuilder("#");
    for (int i = 0; i < 3; i++) {
      int interval = (int) (Math.abs(rgbEnd[i] - rgbStart[i]) * percent); //单个颜色的间隔
      int interColor = Math.min(rgbStart[i], rgbEnd[i]) + interval; //十进制下的插值单个颜色
      /*
       * rgb转为16进制颜色，
       * %02X：
       * X :代表以16进制形式输出；
       * 02 :表示不足两位，前面补0输出；如果超过两位，则实际输出；
       * 如果直接写为 %2x，数据不足两位时，实际输出，即不额外补0输出； 如果超过两位，则实际输出*/
      String format = String.format("%02X", interColor);
      sb.append(format);
    }
    return sb.toString();
  }

  /**
   * 将字符串颜色转为rgb数组(十进制，0~255)
   *
   * @param color 字符串颜色，格式："#000000";
   * @return rgb数组(十进制 ， 0 ~ 255)，格式：[0,55,255]
   */
  public static int[] getRgb(String color) {
    if (!isColor(color)) {
      return null;
    }
    int r = Integer.parseInt(color.substring(1, 3), 16);
    int g = Integer.parseInt(color.substring(3, 5), 16);
    int b = Integer.parseInt(color.substring(5), 16);
    return new int[]{r, g, b};
  }

  /**
   * 判断该字符串是否是颜色字符串，返回Boolean值
   *
   * @param color 颜色字符串
   * @return 是否是颜色字符串。是：true；否：false
   */
  public static boolean isColor(String color) {
    return colorPattern.matcher(color).find();
  }

}
